﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace WpfSocketCommunication
{
    public partial class WindowA : Window
    {
        private Socket _serverSocket;
        private CancellationTokenSource _listenCancellationTokenSource;
        private readonly List<Socket> _connectedClients = new List<Socket>();

        public WindowA()
        {
            InitializeComponent();
        }

        private void StartListeningButton_Click(object sender, RoutedEventArgs e)
        {
            _listenCancellationTokenSource = new CancellationTokenSource();
            try
            {
                _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 8888);
                _serverSocket.Bind(localEndPoint);
                _serverSocket.Listen(10);
                Task.Run(() => ListenForClients(_listenCancellationTokenSource.Token), _listenCancellationTokenSource.Token);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"监听出错: {ex.Message}");
            }
        }

        private void StopListeningButton_Click(object sender, RoutedEventArgs e)
        {
            _listenCancellationTokenSource?.Cancel();
            _serverSocket?.Close();
            foreach (var client in _connectedClients)
            {
                client.Close();
            }
            _connectedClients.Clear();
            ConnectionListBox.Items.Clear();
        }

        private async void ListenForClients(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    Socket clientSocket = await AcceptSocketAsync(_serverSocket, cancellationToken);
                    _connectedClients.Add(clientSocket);
                    Dispatcher.Invoke(() => AddClientToListBox(clientSocket));
                    Task.Run(() => HandleClient(clientSocket, cancellationToken), cancellationToken);
                }
                catch (Exception ex)
                {
                    if (!cancellationToken.IsCancellationRequested)
                    {
                        MessageBox.Show($"接受客户端连接出错: {ex.Message}");
                    }
                }
            }
        }

        private async Task<Socket> AcceptSocketAsync(Socket socket, CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource<Socket>();
            using (cancellationToken.Register(() => tcs.TrySetCanceled()))
            {
                socket.BeginAccept(asyncResult =>
                {
                    try
                    {
                        var client = socket.EndAccept(asyncResult);
                        tcs.TrySetResult(client);
                    }
                    catch (Exception ex)
                    {
                        tcs.TrySetException(ex);
                    }
                }, null);
                return await tcs.Task;
            }
        }

        private async void HandleClient(Socket clientSocket, CancellationToken cancellationToken)
        {
            try
            {
                byte[] buffer = new byte[1024];
                while (!cancellationToken.IsCancellationRequested && clientSocket.Connected)
                {
                    int bytesRead = await ReceiveAsync(clientSocket, buffer, 0, buffer.Length, SocketFlags.None, cancellationToken);
                    if (bytesRead > 0)
                    {
                        string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                        Dispatcher.Invoke(() => AddMessageToClientListBox(clientSocket, message));
                    }
                }
            }
            catch (Exception ex)
            {
                if (!cancellationToken.IsCancellationRequested)
                {
                    MessageBox.Show($"处理客户端出错: {ex.Message}");
                }
            }
            finally
            {
                RemoveClient(clientSocket);
            }
        }

        private async Task<int> ReceiveAsync(Socket socket, byte[] buffer, int offset, int size, SocketFlags socketFlags, CancellationToken cancellationToken)
        {
            var tcs = new TaskCompletionSource<int>();
            using (cancellationToken.Register(() => tcs.TrySetCanceled()))
            {
                socket.BeginReceive(buffer, offset, size, socketFlags, asyncResult =>
                {
                    try
                    {
                        int bytesRead = socket.EndReceive(asyncResult);
                        tcs.TrySetResult(bytesRead);
                    }
                    catch (Exception ex)
                    {
                        tcs.TrySetException(ex);
                    }
                }, null);
                return await tcs.Task;
            }
        }

        private void AddClientToListBox(Socket clientSocket)
        {
            var stackPanel = new StackPanel();
            var messageListBox = new ListBox();
            var inputTextBox = new TextBox();
            var sendButton = new Button { Content = "发送" };
            sendButton.Click += (sender, e) => SendMessageToClient(clientSocket, inputTextBox.Text);
            var disconnectButton = new Button { Content = "停止连接" };
            disconnectButton.Click += (sender, e) => RemoveClient(clientSocket);

            stackPanel.Children.Add(messageListBox);
            stackPanel.Children.Add(inputTextBox);
            stackPanel.Children.Add(sendButton);
            stackPanel.Children.Add(disconnectButton);

            var listBoxItem = new ListBoxItem { Content = stackPanel };
            listBoxItem.Tag = clientSocket;
            ConnectionListBox.Items.Add(listBoxItem);
        }

        private void AddMessageToClientListBox(Socket clientSocket, string message)
        {
            foreach (ListBoxItem item in ConnectionListBox.Items)
            {
                if (item.Tag == clientSocket)
                {
                    var stackPanel = (StackPanel)item.Content;
                    var messageListBox = (ListBox)stackPanel.Children[0];
                    messageListBox.Items.Add(message);
                    break;
                }
            }
        }

        private void SendMessageToClient(Socket clientSocket, string message)
        {
            try
            {
                byte[] buffer = Encoding.UTF8.GetBytes(message);
                clientSocket.Send(buffer);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"发送消息出错: {ex.Message}");
            }
        }

        private void RemoveClient(Socket clientSocket)
        {
            if (_connectedClients.Contains(clientSocket))
            {
                _connectedClients.Remove(clientSocket);
                clientSocket.Close();
                foreach (ListBoxItem item in ConnectionListBox.Items)
                {
                    if (item.Tag == clientSocket)
                    {
                        ConnectionListBox.Items.Remove(item);
                        break;
                    }
                }
            }
        }
    }
}